package com.dragon.datastructure.array;

import java.io.*;
import java.util.Scanner;

/**
 * 稀疏数组
 *
 * @author dragon
 * @since 2019/11/14
 */
public class SparseArray {


    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 1.创建棋盘
        int[][] chessBoard = createChessBoard();
        // 2.添加棋子
        addChessman(chessBoard);
        // 3.转换为稀疏数组
        int[][] sparseArray = convertToSparseArray(chessBoard);
        // 4.序列化到本地
        File storeFile = serializeToLocal(sparseArray);
        // 5.反序列化
        sparseArray = deserializationToSparseArray(storeFile);
        // 6.转换为棋盘
        convertToChessBoard(sparseArray);
    }


    /**
     * 创建一个棋盘，棋盘中的元素规定: 0,空; 1,白子; 2,黑子
     *
     * @return 二维数组
     */
    public static int[][] createChessBoard() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("==输入棋盘行数(正整数)==");
        int lineNum = scanner.nextInt();
        System.out.println("==输入棋盘列数(正整数)==");
        int columnNum = scanner.nextInt();
        int[][] chessBoard = new int[lineNum][columnNum];
        System.out.println("==创建棋盘完成==");

        return chessBoard;
    }

    /**
     * 添加棋子
     *
     * @param chessBoard 棋盘
     */
    public static void addChessman(int[][] chessBoard) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("==输入下棋子的行坐标(从0开始)==");
            int lineNum = scanner.nextInt();
            System.out.println("==输入下棋子的列坐标(从0开始)==");
            int columnNum = scanner.nextInt();
            System.out.println("==输入棋子(1,白子; 2,黑子)==");
            int chessman = scanner.nextInt();
            chessBoard[lineNum][columnNum] = chessman;
            System.out.println("==添加棋子成功==");
            displayChessBoard(chessBoard);
            System.out.println("==是否继续添加棋子(y or n)==");
            String isContinue = scanner.next();
            if ("n".equalsIgnoreCase(isContinue)) {
                break;
            }
        }
        System.out.println("==添加棋子结束==");
    }

    /**
     * 展示棋盘
     *
     * @param chessBoard 棋盘
     */
    public static void displayChessBoard(int[][] chessBoard) {
        System.out.println("==展示棋盘==");
        for (int[] ints : chessBoard) {
            for (int chessman : ints) {
                System.out.printf("%d\t", chessman);
            }
            System.out.println();
        }
    }

    /**
     * 将棋盘二维数组转换为稀疏数组
     *
     * @param chessBoard 棋盘二维数组
     * @return 稀疏数组
     */
    public static int[][] convertToSparseArray(int[][] chessBoard) {
        // 1.根据棋盘二维数组的元素个数来创建稀疏数组
        int chessmanCount = 0;
        for (int[] ints : chessBoard) {
            for (int chessman : ints) {
                if (chessman != 0) {
                    ++chessmanCount;
                }
            }
        }
        // 2.创建稀疏数组
        int[][] sparseArray = new int[chessmanCount + 1][3];
        // 3.添加第一个元素
        int lineCount = chessBoard.length;
        int columnCount = chessBoard[0].length;
        sparseArray[0][0] = lineCount;
        sparseArray[0][1] = columnCount;
        sparseArray[0][2] = chessmanCount;
        // 4.继续添加白子或者黑子
        int index = 1;
        for (int lineNum = 0; lineNum < chessBoard.length; lineNum++) {
            int[] columnArray = chessBoard[lineNum];
            for (int columnNum = 0; columnNum < columnArray.length; columnNum++) {
                if (columnArray[columnNum] != 0) {
                    sparseArray[index][0] = lineNum;
                    sparseArray[index][1] = columnNum;
                    sparseArray[index][2] = columnArray[columnNum];
                    ++index;
                }
            }
        }
        displayChessBoard(sparseArray);

        return sparseArray;
    }

    /**
     * 将稀疏数组写入到本地文件中去
     *
     * @param sparseArray 稀疏数组
     * @return 存储的文件路径
     * @throws IOException
     */
    public static File serializeToLocal(int[][] sparseArray) throws IOException {
        System.out.println("==输入存储路径==");
        Scanner sc = new Scanner(System.in);
        File storeFile = new File(sc.next(), "data.file");
        if (!storeFile.exists()) {
            storeFile.createNewFile();
        }
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(storeFile));
        oos.writeObject(sparseArray);
        oos.close();

        return storeFile;
    }

    /**
     * 反序列化
     *
     * @param storeFile 文件路径
     * @return 稀疏数组
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static int[][] deserializationToSparseArray(File storeFile) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(storeFile));
        int[][] spareArray = (int[][]) ois.readObject();
        ois.close();

        return spareArray;
    }

    /**
     * 将稀疏数组转换为棋盘二维数组
     *
     * @param sparseArray 稀疏数组对象
     * @return 棋盘二维数组
     */
    public static int[][] convertToChessBoard(int[][] sparseArray) {
        // 1.创建棋盘二维数组
        int[][] chessBoard = new int[sparseArray[0][0]][sparseArray[0][1]];
        for (int i = 1; i < sparseArray.length; i++) {
            int[] array = sparseArray[i];
            chessBoard[array[0]][array[1]] = array[2];
        }
        displayChessBoard(chessBoard);

        return chessBoard;
    }

}
